home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 401-425 / disk_421 / dmouse / dmouse-handler.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  16KB  |  638 lines

  1.  
  2. #define DEBUG
  3. /*
  4.  *  DMOUSE-HANDLER.C
  5.  *
  6.  *  (c)Copyright 1989 by Matthew Dillon, All Rights Reserved
  7.  *
  8.  *  V1.20, last revision 3 August 1989
  9.  *
  10.  *  Note on upping the handler process priority.  This is done to cause the
  11.  *  handler task to get CPU before the current input event completes its
  12.  *  processing so intuition calls made by the process are executed before
  13.  *  the event is propogated.  If said intuition calls block, it's ok
  14.  *  because they are not blocking the input handler process.
  15.  */
  16.  
  17. #include "dmouse.h"
  18. #include <hardware/custom.h>
  19. #include <hardware/dmabits.h>
  20. #include <graphics/gfxmacros.h>
  21.  
  22.  
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26.  
  27. /*typedef struct Layer          LAYER;*/
  28. typedef IE  *IEP;
  29. typedef struct IORequest    IORequest;
  30.  
  31. __far extern struct Custom custom;
  32.  
  33. DMS    *Dms               = NULL;
  34. IBASE    *IntuitionBase           = NULL;
  35. GFXBASE *GfxBase           = NULL;
  36. struct LayersBase  *LayersBase = NULL;
  37. /*
  38. struct ExecBase    *SysBase    = NULL;
  39. */
  40. struct DosLibrary  *DOSBase    = NULL;
  41.  
  42. static PORT    *IOPort = NULL;     /*    For IPC messages          */
  43. static LIST    BlankList;        /*    list of external blanker programs */
  44.  
  45. static char    STimedout = 0;
  46. static char    MTimedout = 0;
  47. static long    STime = 0, MTime = 0;
  48. #ifdef DEBUG
  49. static long    DBFh = NULL;
  50. #endif
  51. static void    *ReqCache = NULL;   /*    to prevent massive AllocMem()s    */
  52.  
  53.  
  54. NS    Ns = {    0, 0, 64, -1, 1, -1, -1, 0, CUSTOMSCREEN|SCREENQUIET };
  55.  
  56.  
  57. IE DummyIE = { 0 };
  58.  
  59. short    NRMe    = 0;    /*  Don't Repeat Mouse Events   */
  60.  
  61. IE *handler();
  62.  
  63. int doipcmsg(short);
  64. void sendrequest(long, IE *);
  65. void DeleteBlanker(IORequest *);
  66. LAYER *WhichMouseLayer(void);
  67. LAYER *WhichMouseLayer(void);
  68.  
  69. void
  70. _main()
  71. {
  72.     DMS *dms;
  73.     IOR *ior;
  74.     INT addhand;
  75.     IBASE *ib;
  76.  
  77.     /*
  78.     SysBase = *(struct ExecBase **)4;
  79.     */
  80.     DOSBase = (struct DosLibrary *)OpenLibrary("dos.library", 0);
  81.     {
  82.     PROC *proc = (PROC *)FindTask(NULL);
  83.     proc->pr_ConsoleTask = NULL;
  84.     }
  85.     NRMe = 0;
  86.     dms = Dms = (DMS *)FindPort(PORTNAME);
  87.     if (!dms)
  88.     return;
  89.     dms->Port.mp_Flags = PA_SIGNAL;
  90.     dms->Port.mp_SigBit = AllocSignal(-1);
  91.     dms->Port.mp_SigTask = FindTask(NULL);
  92.     dms->HandTask = dms->Port.mp_SigTask;
  93.     ior = CreateStdIO(&dms->Port);
  94.     IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 0);
  95.     GfxBase = (struct GfxBase *)OpenLibrary("graphics.library", 0);
  96.     LayersBase = (struct LayersBase *)OpenLibrary("layers.library", 0);
  97.     IOPort = CreatePort("DMouse.ipc", 0);
  98.     NewList(&BlankList);
  99.  
  100.     if (!IntuitionBase || !GfxBase || !LayersBase)
  101.     goto startupfail;
  102.  
  103.     ib = IntuitionBase;
  104.  
  105.     clrmem(&addhand, sizeof(addhand));
  106.     addhand.is_Node.ln_Name = "DMouse";
  107.     addhand.is_Node.ln_Pri = dms->IPri;
  108.     addhand.is_Code = (FPTR)handler;
  109.     addhand.is_Data = NULL;
  110.  
  111.     if (OpenDevice("input.device", 0, ior, 0)) {
  112.     goto startupfail;
  113.     } else {
  114.     SCR *scr = NULL;
  115.     short sproff = 0;
  116.     long ipc_mask;
  117.  
  118.     Signal(dms->ShakeTask, 1 << dms->ShakeSig);
  119.     ior->io_Command = IND_ADDHANDLER;
  120.     ior->io_Data = (APTR)&addhand;
  121.     ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  122.     DoIO(ior);
  123.  
  124.     ipc_mask = 1 << IOPort->mp_SigBit;
  125.  
  126.     for (;;) {
  127.         long sigs = Wait(SBF_C|(1<<dms->Port.mp_SigBit)|ipc_mask);
  128.         if (sigs & (1 << dms->Port.mp_SigBit)) {
  129.         REQ *msg;
  130.         while (msg = (REQ *)GetMsg(&dms->Port)) {
  131.             switch((long)msg->Msg.mn_Node.ln_Name) {
  132.             case REQ_SCREENON:
  133.             if (scr)
  134.                 CloseScreen(scr);
  135.             scr = NULL;
  136.             doipcmsg(0x82);
  137.             break;
  138.             case REQ_SCREENOFF:
  139.             if (scr)
  140.                 ScreenToFront(scr);
  141.             if (doipcmsg(0x83) == 0 && scr == NULL) {
  142.                 if (scr = OpenScreen(&Ns))
  143.                 SetRGB4(&scr->ViewPort, 0, 0, 0, 0);
  144.             }
  145.             break;
  146.             case REQ_MOUSEON:
  147.             if (sproff) {
  148.                 ON_SPRITE;
  149.                 sproff = 0;
  150.             }
  151.             doipcmsg(0x80);
  152.             break;
  153.             case REQ_MOUSEOFF:
  154.             /*
  155.              *  note, sometimes the sprite gets turned on again, so
  156.              *  we re-off it every mouse-ptr-timeout
  157.              */
  158.             if (doipcmsg(0x81) == 0) {
  159.                 WaitTOF();
  160.                 OFF_SPRITE;
  161.                 custom.spr[0].dataa=0;  /*    sprite0 DMA    */
  162.                 custom.spr[0].datab=0;  /*    data register    */
  163.                 sproff = 1;
  164.             }
  165.             break;
  166.             case REQ_DOCMD:
  167.             {
  168.                 long fh = (long)Open("nil:", 1006);
  169.                 Execute(dms->Cmd, NULL, fh);
  170.                 if (fh)
  171.                 Close(fh);
  172.             }
  173.             break;
  174.             case REQ_RAWMOUSE:
  175.             {
  176.                 LAYER *layer;
  177.  
  178.                 NRMe = 0;
  179.                 Forbid();
  180.                 layer = WhichMouseLayer();
  181.                 if (msg->ie_Code == IECODE_RBUTTON && dms->LMBEnable && (msg->ie_Qualifier & dms->RQual)) {
  182.                 WIN *win;
  183.                 if (layer && (win = (WIN *)layer->Window) && !(win->Flags & BACKDROP) && (win->NextWindow || win->WScreen->FirstWindow != win)) {
  184.                     if (dms->FBEnable || (win->Flags & WINDOWDEPTH)) {
  185.                     if (dms->Workbench)
  186.                         WindowToBack(win);
  187.                     else
  188.                         BehindLayer(0, layer);
  189.                     }
  190.                 } else if (ib->FirstScreen)
  191.                     ScreenToBack(ib->FirstScreen);
  192.                 }
  193.                 if (layer && layer->Window) {
  194.                 if (msg->ie_Code == IECODE_LBUTTON && !(((WIN *)layer->Window)->Flags & BACKDROP) && dms->LMBEnable && layer->ClipRect && layer->ClipRect->Next) {
  195.                     /*
  196.                      *    Note: Case where it is the 'first' click in a series, where dms->CTime is
  197.                      *          garbage, works properly no matter what DoubleClick returns.
  198.                      */
  199.                     if (dms->LQual == 0 || (msg->ie_Qualifier & dms->LQual)) {
  200.                     if ((APTR)dms->CWin == layer->Window && DoubleClick(dms->CTime.tv_secs, dms->CTime.tv_micro, msg->ie_TimeStamp.tv_secs, msg->ie_TimeStamp.tv_micro))
  201.                         --dms->CLeft;
  202.                     else
  203.                         dms->CLeft = dms->Clicks - 1;
  204.                     dms->CTime = msg->ie_TimeStamp;
  205.                     dms->CWin = (WIN *)layer->Window;
  206.                     if (dms->CLeft == 0) {
  207.                         dms->CLeft = dms->Clicks;
  208.                         if (dms->FBEnable || (((WIN *)layer->Window)->Flags & WINDOWDEPTH)) {
  209.                         if (dms->Workbench)
  210.                             WindowToFront((WIN *)layer->Window);
  211.                         else
  212.                             UpfrontLayer(0, layer);
  213.                         }
  214.                     }
  215.                     }
  216.                 }
  217.                 if ((dms->AAEnable & 1) && (void *)layer->Window != (void *)ib->ActiveWindow && msg->ie_Code == IECODE_NOBUTTON && !(msg->ie_Qualifier & 0x7000)) {
  218.                     if (!ib->ActiveWindow || !ib->ActiveWindow->FirstRequest)
  219.                     ActivateWindow((WIN *)layer->Window);
  220.                 }
  221.                 }
  222.                 Permit();
  223.             }
  224.             break;
  225.             case REQ_RAWKEY:
  226.             {
  227.                 LAYER *layer;
  228.  
  229.                 Forbid();
  230.                 layer = WhichMouseLayer();
  231.                 if (layer && layer->Window && (void *)layer->Window != (void *)ib->ActiveWindow) {
  232.                 if (!ib->ActiveWindow || !ib->ActiveWindow->FirstRequest)
  233.                     ActivateWindow((WIN *)layer->Window);
  234.                 }
  235.                 Permit();
  236.             }
  237.             break;
  238. #ifdef DEBUG
  239.             case REQ_DEBUG:
  240.             {
  241.                 char buf[128];
  242.                 if (!DBFh) {
  243.                 DBFh = Open("con:0/0/400/100/dmouse-debug", 1006);
  244.                 if (!DBFh)
  245.                     break;
  246.                 }
  247.                 sprintf(buf, "%02lx %04lx %04lx (%d,%d)\n",
  248.                 msg->ie_Class,
  249.                 msg->ie_Code,
  250.                 msg->ie_Qualifier,
  251.                 msg->rq_X,
  252.                 msg->rq_Y
  253.                 );
  254.                 Write(DBFh, buf, strlen(buf));
  255.             }
  256.             break;
  257.             case REQ_DEBUGOFF:
  258.             if (DBFh) {
  259.                 Close(DBFh);
  260.                 DBFh = NULL;
  261.             }
  262.             break;
  263. #endif
  264.             }
  265.             if (ReqCache == NULL && msg->Msg.mn_Length == sizeof(REQ))
  266.             ReqCache = (void *)msg;
  267.             else
  268.             FreeMem(msg, msg->Msg.mn_Length);
  269.         }
  270.         }
  271.         if (sigs & SBF_C)
  272.         break;
  273.  
  274.         /*
  275.          *    IPC request.
  276.          */
  277.  
  278.         if (sigs & ipc_mask) {
  279.         IORequest *ior;
  280.         while (ior = (IORequest *)GetMsg(IOPort)) {
  281.             long req = 0;
  282.  
  283.             if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
  284.             FreeMem(ior, ior->io_Message.mn_Length);
  285.             continue;
  286.             }
  287.  
  288.             ior->io_Error = 0;
  289.             switch(ior->io_Command) {
  290.             case 0x80:    /* mouse on  */
  291.             req = REQ_MOUSEON;
  292.             break;
  293.             case 0x81:    /* mouse off */
  294.             req = REQ_MOUSEOFF;
  295.             MTimedout = 1;
  296.             break;
  297.             case 0x82:    /* screen on */
  298.             req = REQ_SCREENON;
  299.             break;
  300.             case 0x83:    /* screen off*/
  301.             req = REQ_SCREENOFF;
  302.             STimedout = 1;
  303.             break;
  304.             case 0x84:    /* add hand  */
  305.             AddHead(&BlankList, ior);
  306.             ior = NULL;
  307.             break;
  308.             case 0x85:    /* rem hand  */
  309.             DeleteBlanker(ior);
  310.             ior = NULL;
  311.             break;
  312.             }
  313.             if (req)
  314.             sendrequest(req, NULL);
  315.             if (ior)
  316.             ReplyMsg(&ior->io_Message);
  317.         }
  318.         }
  319.     }
  320. #ifdef DEBUG
  321.     if (DBFh) {
  322.         Close(DBFh);
  323.         DBFh = NULL;
  324.     }
  325. #endif
  326.     ior->io_Command = IND_REMHANDLER;
  327.     ior->io_Data = (APTR)&addhand;
  328.     ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  329.     DoIO(ior);
  330.  
  331.     ior->io_Command = IND_WRITEEVENT;    /*  NULL EVENT    */
  332.     ior->io_Length = sizeof(IE);
  333.     ior->io_Data = (APTR)&DummyIE;
  334.     ior->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  335.     DoIO(ior);
  336.     CloseDevice(ior);
  337.     {
  338.         MSG *msg;
  339.         while (msg = GetMsg(&dms->Port))
  340.         FreeMem(msg, msg->mn_Length);
  341.     }
  342.     if (scr)
  343.         CloseScreen(scr);
  344.  
  345.     if (sproff) {
  346.         ON_SPRITE;
  347.         sproff = 0;
  348.     }
  349.     }
  350.     goto closedown;
  351. startupfail:
  352.     dms->StartupError = 1;
  353.     Signal(dms->ShakeTask, 1 << dms->ShakeSig);
  354.     Wait(SBF_C);
  355. closedown:
  356.     DeleteStdIO(ior);
  357. fail:
  358.     if (IOPort) {
  359.     IORequest *ior;     /*    wait for RemReq messages */
  360.  
  361.     doipcmsg(0x86);     /*  send closedown requests  */
  362.     Forbid();
  363.     while (GetHead(&BlankList)) {
  364.         WaitPort(IOPort);
  365.         while (ior = (IORequest *)GetMsg(IOPort)) {
  366.         if (ior->io_Message.mn_Node.ln_Type == NT_REPLYMSG) {
  367.             FreeMem(ior, ior->io_Message.mn_Length);
  368.             continue;
  369.         }
  370.         if (ior->io_Command == 0x85)    /*  receive remove req  */
  371.             DeleteBlanker(ior);
  372.         else
  373.             ReplyMsg(&ior->io_Message);              /*  ignore other reqs   */
  374.         }
  375.     }
  376.     DeletePort(IOPort);
  377.     Permit();
  378.     }
  379.     if (IntuitionBase)
  380.     CloseLibrary((LIB *)IntuitionBase);
  381.     if (GfxBase)
  382.     CloseLibrary((LIB *)GfxBase);
  383.     if (LayersBase)
  384.     CloseLibrary((LIB *)LayersBase);
  385.     CloseLibrary((LIB *)DOSBase);
  386.     if (ReqCache)
  387.     FreeMem(ReqCache, sizeof(REQ));
  388.     Forbid();
  389.     Signal(dms->ShakeTask, 1 << dms->ShakeSig);
  390. }
  391.  
  392. void
  393. DeleteBlanker(ior)
  394. IORequest *ior;
  395. {
  396.     IORequest *io2;
  397.  
  398.     ior->io_Error = 0;
  399.     for (io2 = (IORequest *)GetHead(&BlankList); io2; io2 = (IORequest *)GetSucc(io2)) {
  400.     if (io2->io_Unit == ior->io_Unit) {
  401.         Remove(io2);
  402.         if (ior)
  403.         ReplyMsg(&ior->io_Message);
  404.         ReplyMsg(&io2->io_Message);
  405.         ior = NULL;
  406.     }
  407.     }
  408.     if (ior) {
  409.     ior->io_Error = -1;
  410.     ReplyMsg(&ior->io_Message);
  411.     }
  412. }
  413.  
  414. doipcmsg(cmd)
  415. short cmd;
  416. {
  417.     short count = 0;
  418.     short flags = 1 << (cmd & 0x7F);    /*  enable flags */
  419.     IORequest *iob, *io;
  420.  
  421.     for (iob = (IORequest *)GetHead(&BlankList); iob; iob = (IORequest *)GetSucc(iob)) {
  422.     if (cmd == 0x86 || (iob->io_Flags & flags)) {
  423.         io = AllocMem(sizeof(IORequest), MEMF_PUBLIC|MEMF_CLEAR);
  424.         if (io) {
  425.         io->io_Command = cmd;
  426.         io->io_Unit = iob->io_Unit;
  427.         io->io_Message.mn_ReplyPort = IOPort;
  428.         io->io_Message.mn_Length = sizeof(IORequest);
  429.         PutMsg(iob->io_Message.mn_ReplyPort, &io->io_Message);
  430.         ++count;
  431.         }
  432.     }
  433.     }
  434.     return((int)count);
  435. }
  436.  
  437. /*
  438.  *  The INPUT.DEVICE HANDLER
  439.  */
  440.  
  441. __geta4 IE *
  442. CHandler(Ev)
  443. IE *Ev;
  444. {
  445.     IE *ev;
  446.     DMS *dms;
  447.  
  448.     dms = Dms;
  449.     for (ev = Ev; ev; ev = ev->ie_NextEvent) {  /*  chgd feb 1990 3/Ev->ev */
  450. #ifdef DEBUG
  451.     if (dms->Debug) {
  452.         if (ev->ie_Class != IECLASS_TIMER)
  453.         sendrequest(REQ_DEBUG, ev);
  454.     } else if (DBFh) {
  455.         sendrequest(REQ_DEBUGOFF, ev);
  456.     }
  457. #endif
  458.     switch(ev->ie_Class) {
  459.     case IECLASS_RAWMOUSE:
  460.         /*
  461.          *    Mouse events restore both the screen and mouse pointer.
  462.          */
  463.  
  464.         STime = ev->ie_TimeStamp.tv_secs + dms->STo;
  465.         MTime = ev->ie_TimeStamp.tv_secs + dms->MTo;
  466.         if (STimedout)
  467.         sendrequest(REQ_SCREENON, ev);
  468.         if (MTimedout)
  469.         sendrequest(REQ_MOUSEON, ev);
  470.         STimedout = MTimedout = 0;
  471.  
  472.         /*
  473.          *    Mouse Acceleration
  474.          */
  475.         {
  476.         short n;
  477.         short s;
  478.  
  479.         if (dms->Acc != 1) {
  480.             n = ev->ie_X;
  481.             s = 1;
  482.             if (n < 0) {
  483.             n = -n;
  484.             s = -1;
  485.             }
  486.             if (n > dms->AThresh)
  487.             ev->ie_X = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1);
  488.             n = ev->ie_Y;
  489.             s = 1;
  490.             if (n < 0) {
  491.             n = -n;
  492.             s = -1;
  493.             }
  494.             if (n > dms->AThresh)
  495.             ev->ie_Y = s * (short)((n - dms->AThresh - 1) * dms->Acc + dms->AThresh + 1);
  496.         }
  497.         }
  498.  
  499.         /*
  500.          *    Auto Activate and LMB (win/scrn front/bak)
  501.          */
  502.  
  503.         if (dms->LMBEnable && ev->ie_Code == IECODE_RBUTTON && (ev->ie_Qualifier & dms->RQual))
  504.         ev->ie_Class = IECLASS_NULL;    /*  remove event    */
  505.         if (NRMe == 0 && ((dms->AAEnable & 1) || dms->LMBEnable)) {
  506.         short old;
  507.         NRMe = 1;
  508.         if (ev->ie_Code != IECODE_NOBUTTON)
  509.             old = SetTaskPri(dms->Port.mp_SigTask, 21);
  510.         sendrequest(REQ_RAWMOUSE, ev);
  511.         if (ev->ie_Code != IECODE_NOBUTTON) {
  512.             SetTaskPri(dms->Port.mp_SigTask, old);
  513.             WaitTOF();  /*  cause a delay   */
  514.         }
  515.         }
  516.         break;
  517.     case IECLASS_RAWKEY:
  518.         /*
  519.          *    Keyboard events will kill the screen timeout but not
  520.          *    the mouse timeout.  Note that the priority of the
  521.          *    co-process must be upped to ensure it is able to make the
  522.          *    window active before the keystroke is passed further.
  523.          *
  524.          *    key releases are ignored
  525.          *
  526.          *    note: ie_Qualifier may or may not have bit 15 set
  527.          */
  528.         if (ev->ie_Code & 0x80)
  529.         break;
  530.         if (dms->AAEnable & 2) {
  531.         short old;
  532.         old = SetTaskPri(dms->Port.mp_SigTask, 21);
  533.         sendrequest(REQ_RAWKEY, ev);
  534.         SetTaskPri(dms->Port.mp_SigTask, old);
  535.         WaitTOF();  /*  cause a delay   */
  536.         }
  537.         STime = ev->ie_TimeStamp.tv_secs + dms->STo;
  538.         if (STimedout) {
  539.         sendrequest(REQ_SCREENON, ev);
  540.         if (dms->MTo == 0)
  541.             sendrequest(REQ_MOUSEON, ev);
  542.         }
  543.         STimedout = 0;
  544.  
  545.         if (ev->ie_Code == dms->Code && (ev->ie_Qualifier | 0x8000) == dms->Qual) {
  546.         sendrequest(REQ_DOCMD, ev);
  547.         ev->ie_Class = IECLASS_NULL;    /*  remove event    */
  548.         }
  549.         break;
  550.     case IECLASS_TIMER:
  551.         /*
  552.          *    On a timer event, if timeout has occured execute the operation
  553.          *    and reset the timeout.    Note that this will cause continuous
  554.          *    timeouts every STo and MTo seconds... required because at any
  555.          *    time Intuition might turn the mouse back on or open a screen or
  556.          *    something and I want the blanker's to work in the long run.
  557.          */
  558.         {
  559.         long old;
  560.         if (dms->Reset) {
  561.             dms->Reset = 0;
  562.             STime = ev->ie_TimeStamp.tv_secs + dms->STo;
  563.             MTime = ev->ie_TimeStamp.tv_secs + dms->MTo;
  564.         }
  565.         if (dms->STo && (old = STime - ev->ie_TimeStamp.tv_secs) < 0) {
  566.             STime = ev->ie_TimeStamp.tv_secs + dms->STo + 10;
  567.             STimedout = 1;
  568.             MTimedout = 1;
  569.             if (old > -10) {
  570.             sendrequest(REQ_SCREENOFF, ev);
  571.             sendrequest(REQ_MOUSEOFF, ev);
  572.             }
  573.         }
  574.         if (dms->MTo && (old = MTime - ev->ie_TimeStamp.tv_secs) < 0) {
  575.             MTime = ev->ie_TimeStamp.tv_secs + dms->MTo + 1;
  576.             MTimedout = 1;
  577.             if (old > -10)
  578.             sendrequest(REQ_MOUSEOFF, ev);
  579.         }
  580.         }
  581.         break;
  582.     }
  583.     }
  584.     return(Ev);
  585. }
  586.  
  587. void
  588. sendrequest(creq, ev)
  589. long creq;
  590. IE *ev;
  591. {
  592.     REQ *req;
  593.  
  594.     if (req = ReqCache)
  595.     ReqCache = NULL;
  596.     else
  597.     req = AllocMem(sizeof(REQ), MEMF_PUBLIC);
  598.  
  599.     if (req) {
  600.     req->Msg.mn_Node.ln_Name = (char *)creq;
  601.     req->Msg.mn_ReplyPort = NULL;
  602.     req->Msg.mn_Length = sizeof(REQ);
  603.     if (ev) {
  604.         req->ie_Class= ev->ie_Class;
  605.         req->ie_Code = ev->ie_Code;
  606.         req->ie_Qualifier = ev->ie_Qualifier;
  607.         req->ie_TimeStamp = ev->ie_TimeStamp;
  608.         req->rq_X = ev->ie_X;
  609.         req->rq_Y = ev->ie_Y;
  610.     }
  611.     PutMsg(&Dms->Port, (MSG *)req);
  612.     }
  613. }
  614.  
  615. LAYER *
  616. WhichMouseLayer()
  617. {
  618.     IBASE *ib = IntuitionBase;
  619.     LAYER *layer = NULL;
  620.     SCR *scr = ib->FirstScreen;
  621.  
  622.     for (scr = ib->FirstScreen; scr; scr = scr->NextScreen) {
  623.     short mousey = ib->MouseY;
  624.     short mousex = ib->MouseX;
  625.     if (!(scr->ViewPort.Modes & LACE))
  626.         mousey >>= 1;
  627.     if (!(scr->ViewPort.Modes & HIRES))
  628.         mousex >>= 1;
  629.     if (layer = WhichLayer(&scr->LayerInfo, mousex - scr->ViewPort.DxOffset, mousey - scr->ViewPort.DyOffset))
  630.         break;
  631.     if (mousey >= scr->ViewPort.DyOffset)
  632.         break;
  633.     }
  634.     return(layer);
  635. }
  636.  
  637.  
  638.